import createProps from '../js/createProps.js' import { replaceTags } from '../js/replaceTags.js' class Foundations extends HTMLElement { constructor() { super() // Properties this.hasSelectors = false this.replace = '' //Events this.boundOnLoad = this.onLoad.bind(this) } connectedCallback() { createProps(this) this.init() this.bindEvent() this.checkSelectors() this.replaceTags() } init() { document.documentElement.classList.add('mU') } onClick() { document.documentElement.classList.remove('kU') document.documentElement.classList.remove('tU') document.documentElement.classList.add('mU') } onKeyTab(e) { if (e.key === 'Tab') { document.documentElement.classList.add('kU') } } onTouch() { document.documentElement.classList.remove('mU') document.documentElement.classList.remove('kU') document.documentElement.classList.add('tU') // Disable mouse event during 300ms to not fire mousedown after touchstart // 300ms delay is not enough, 350ms is working fine // To know more about delay between touchstart and mousedown: https://web.dev/mobile-touchandmouse/ document.removeEventListener('mousedown', this.onClick) setTimeout(() => { document.addEventListener('mousedown', this.onClick) }, 350) } replaceTags() { if (this.replace === '') { return } const tags = this.replace.split(',') const main = document.querySelector('main') tags.forEach(tag => { replaceTags(tag.trim(), main) }) } checkSelectors() { // This is needed until :has css selector is fully supported if (!this.hasSelectors) { return } this.hasSelectors = this.hasSelectors.split(',') this.existingSelectors() this.observeSelectors() } existingSelectors () { // This is needed until :has css selector is fully supported this.hasSelectors.forEach( selector => { if (document.querySelector(selector)) { this.foundedSelector(selector) } }) } foundedSelector(selector) { // This is needed until :has css selector is fully supported let index = this.hasSelectors.indexOf(selector) this.hasSelectors.splice(index, 1) document.documentElement.classList.add('has-' + this.classClean(selector)) } classClean(selector) { // This is needed until :has css selector is fully supported return selector.trim().replace('.', '') } observeSelectors() { // This is needed until :has css selector is fully supported const nb_selectors = this.hasSelectors.length let nb_founds = 0 if (nb_founds === nb_selectors) { return } const self = this this.observer = new MutationObserver(mutations => { mutations.forEach(function (mutation) { mutation.addedNodes.forEach(function (added_node) { if (added_node.nodeType === 1) { self.hasSelectors.forEach( selector => { if (document.querySelector(selector)) { self.foundedSelector(selector) nb_founds += 1 if (nb_founds === nb_selectors) { self.observer.disconnect() } } }) } }) }) }) this.observer.observe(document.body, { subtree: true, childList: true }) } onLoad() { // This is needed until :has css selector is fully supported this.observer?.disconnect() } bindEvent() { this.unbindEvent() document.addEventListener('mousedown', this.onClick) document.addEventListener('keydown', this.onKeyTab) document.addEventListener('touchstart', this.onTouch, false) window.addEventListener('load', this.boundOnLoad) } unbindEvent() { document.removeEventListener('mousedown', this.onClick) document.removeEventListener('keydown', this.onKeyTab) document.removeEventListener('touchstart', this.onTouch, false) window.removeEventListener('load', this.boundOnLoad) } disconnectedCallback() { this.unbindEvent() } } customElements.get('u-foundations') || customElements.define('u-foundations', Foundations) export default Foundations